using System;
//using System.Configuration.ConfigurationSettings;
using System.Configuration;
using System.Data;
using System.Diagnostics;
//using System.Xml.Linq;
using System.Windows.Forms;
//using System.Linq;
//using clsVariables;
using MySql.Data.MySqlClient;
using MySql.Data.Types;

//'
public class clsBBDD_MySQL
{
    //enum eTipoSalidaFecha  { SQlSrv, MySQl }
    private static MySqlDataAdapter Da;
    private static MySqlCommandBuilder Cb;
    //Private Shared Dt As DataTable
    //'
    /// <summary>
    /// Transforma una fecha MySQl en una Date (Net)
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public static DateTime? MySql_ConvertirMySqlDateTimeToDate(object value)
    {
        MySqlDateTime d;
        //'
        if (value == DBNull.Value || value == null)
        {
            return null; // Date.MinValue
        }
        else if (value is MySqlDateTime)
        {
            d = (MySqlDateTime)value;
            if (!Microsoft.VisualBasic.Information.IsNumeric(d.Day.ToString()) || (!d.IsValidDateTime))
            {
                return null;
            }
            else
            {
                return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second);
            }
        }
        else if (value is DateTime)
        {
            return Convert.ToDateTime(value);
        }
        else
        {
            Utiles.Errores.LanzarError(null, "ConvertirFechaNET", "El valor datFecha no corresponde con un DateMySQL ni Date.", null, MessageBoxIcon.Exclamation, true);
            return null;
        }
    }
    //
    //public static object cFechaOut(object datFecha, bool bolDevolucionTipoString = false) // MySqlDateTime ' Date) As Object
    //{ }
    //'
    /// <summary>
    /// Devuelve un "MySqlDateTime" desde un Date. Sino es un provider MySQl o le pasas diferente de date devuelve el mismo objeto
    /// Ej1: Item("EdatMaxima") = BS_MySQL.cFechaMySql(Me.uccEdatMaxima.Value)
    /// Ej2: clsBBDD_MySQL.cFecha( DateTime.Now,true)
    /// </summary>
    /// <param name="datFecha">MySqlDateTime or Date</param>
    /// <param name="bolDevolucionTipoString">Si devuelve la fecha en tipo string ('yyyy-MM-dd hh:mm:ss') o en object</param>
    /// <returns></returns>
    public static object cFecha(object datFecha, bool bolDevolucionTipoString = false) // MySqlDateTime ' Date) As Object
    {
        //If e_ProviderNombreAplicacion = eProviderNombre.MySqlClient AndAlso TypeOf datFecha Is Date Then
        //   Dim d As Date = datFecha
        //   Return New MySqlDateTime(d)
        //Else
        //   Return datFecha
        //End If
        object Ret = datFecha;
        switch (clsVariables.e_ProviderNombreAplicacion)
        {
            case clsVariables.eProviderNombre.MySqlClient:
                if (datFecha is MySqlDateTime)
                {
                    if (bolDevolucionTipoString)

                    //{ Ret = String.Format("{0:u}", Convert.ToDateTime(datFecha)); } // "2008-03-09 16:05:07Z" 
                    { Ret = System.Convert.ToDateTime(datFecha).ToString("yyyy-MM-dd HH:mm:ss"); }
                    else { Ret = (MySqlDateTime)datFecha; }
                }
                else if (datFecha is DateTime)
                {
                    if (bolDevolucionTipoString)
                    //{ Ret = String.Format("{0:u}", datFecha); } // "2008-03-09 16:05:07Z"... y paque sirve la Z?En los inserts me da por saco
                    { Ret = ((DateTime)datFecha).ToString("yyyy-MM-dd HH:mm:ss"); }
                    else { DateTime d = (DateTime)datFecha; Ret = new MySqlDateTime(d); }
                    //ret = Format(ret, "yyyy-DD-dd hh:mm:ss")
                }
                break;
            //
            case clsVariables.eProviderNombre.SqlClient:
                if (datFecha is DateTime)
                {
                    if (bolDevolucionTipoString)
                    //{ Ret = String.Format("{0:u}", datFecha); } // "2008-03-09 16:05:07Z"... y paque sirve la Z?En los inserts me da por saco
                    { Ret = ((DateTime)datFecha).ToString("yyyy-MM-dd HH:mm:ss"); }
                    else { DateTime d = (DateTime)datFecha; Ret = new MySqlDateTime(d); }
                    //ret = Format(ret, "yyyy-DD-dd hh:mm:ss")
                }
                break;
        }
        return Ret;
    }
    //'
    //'
    /// <summary>
    /// Gestion datos usando la librería de MySql. A poder ser usar la del Factory siempre
    /// </summary>
    /// <remarks></remarks>
    public class GestionDatos
    {
        //private static DataTable DtObtenerAux(string selectCommandText, clsVariables.e_TipoOrigen origen, bool bolObtenerSchema)
        //{
        //    DataTable dt = null;
        //    try
        //    {
        //        if (!selectCommandText.Equals(string.Empty))
        //        {
        //            ConnectionStringSettings c = clsVariables.e_Cc(origen);
        //            MySqlDataAdapter adapter = new MySqlDataAdapter(selectCommandText, new MySqlConnection(c.ConnectionString));
        //            DataSet Ds = new DataSet();
        //            adapter.Fill(Ds, "datos");
        //            return Ds.Tables[0];
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        //IsItCRMException.Process(ex, "Error al Ejecutar el Comando");
        //    }
        //    return dt;
        //}
        /// <summary>
        /// Cuando vacias el nav borrando todos los registros
        /// TODO: en combo doble no se pq. misterioso motivo cuando borras todos los registros en el nav y agregas uno nuevo no obtiene ok.. hay q llamar 2 veces a DtObtener seguidas
        /// </summary>
        /// <param name="selectCommandText"></param>
        /// <param name="origen"></param>
        /// <param name="bolObtenerSchema"></param>
        /// <returns></returns>
        public static DataTable DtObtener(string selectCommandText, clsVariables.e_TipoOrigen origen, bool bolObtenerSchema)
        {
            // DataTable dtDatos = null;
            //DataTable Ret = new DataTable();
            //Ret.DataSet.EnforceConstraints = false;
            //'
            try
            {
                //DataTable Dt2 = DtObtener2(selectCommandText, origen, bolObtenerSchema);
                //return Dt2;
                //
                //Console.WriteLine(selectCommandText)
                //'
                //Dim c As ConnectionStringSettings = e_Cc(origen)
                //'FactoryBBDD = DbProviderFactories.GetFactory(c.ProviderName)
                //'
                //Using cn2 As New MySqlConnection(c.ConnectionString)
                //   Dim da2 As MySqlDataAdapter = New MySqlDataAdapter(selectCommandText, cn2)
                //   Dim cb As New MySqlCommandBuilder(da2)

                //   cb.QuotePrefix = "["
                //   cb.QuoteSuffix = "]"
                //   Dt = New DataTable
                //   da2.Fill(Dt)
                //End Using
                //'
                ConnectionStringSettings c = clsVariables.e_Cc(origen);
                DataSet Ds = new DataSet { EnforceConstraints = false };
                using (MySqlConnection cn = new MySqlConnection(c.ConnectionString) { ConnectionString = c.ConnectionString })
                {
                    cn.Open();
                    using (MySqlCommand cm = new MySqlCommand { Connection = cn, CommandType = CommandType.Text, CommandText = selectCommandText /* "Select * FROM vis"*/ })
                    {
                        //Dim r As IDataReader = cm.ExecuteReader(CommandBehavior.CloseConnection)
                        // Create the DbDataAdapter.
                        using (MySqlDataAdapter adapter = new MySqlDataAdapter { SelectCommand = cm })
                        {
                            if (bolObtenerSchema)
                            {
                                //DataTable dtSchema = new DataTable() {TableName = "dtSchema" };
                                adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
                                //No acaba de funcionar ok el MaxLengh. NO hace falta con lo anterior al parecer: http://www.vbforums.com/showthread.php?t=395978
                                //adapter.FillSchema(dtSchema, SchemaType.Source);     
                                //Ds.Tables.Add(dtSchema);
                            }
                            //dtDatos = new DataTable() { TableName = "dtDatos" };
                            //Ds.Tables.Add(dtDatos); 
                            adapter.Fill(Ds);// (dtDatos);
                            // DataTable Dt2 =  DtObtener2(selectCommandText, origen, bolObtenerSchema);
                        }
                    }

                }
                //Ds.EnforceConstraints = true ;
                return Ds.Tables[0];
                //return dtDatos;
                //
            }
            catch (Exception ex)
            {
                throw (ex);
                //return null;
            }
        }
        //'
        /// <summary>
        /// Recuperar un dataTable desde un origen. Especial para MySQl.
        /// NO he podido hacer servir el genérico poq no puedo poner un new mysql.datetime en una row con ese tipo de campo
        /// dos días buscando solucioes y nada.. paso!
        /// </summary>
        /// <param name="selectCommandText"></param>
        /// <param name="origen"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static DataTable DtObtenerConUpdate(string selectCommandText, clsVariables.e_TipoOrigen origen)
        {
            MySqlDataAdapter Da;
            // Dim Cb As MySqlCommandBuilder
            DataTable Dt = null;
            //'
            try
            {
                ConnectionStringSettings c = clsVariables.e_Cc(origen);
                //FactoryBBDD = DbProviderFactories.GetFactory(c.ProviderName)
                //Dim cn As DbConnection = FactoryBBDD.CreateConnection
                //cn.ConnectionString = c.ConnectionString
                // da = New SqlDataAdapter(sSelect, sConn)
                Da = new MySqlDataAdapter(selectCommandText, c.ConnectionString); //sConn)
                Cb = new MySqlCommandBuilder(Da);
                Cb.QuotePrefix = "";
                Cb.QuoteSuffix = "";
                //
                Dt = new DataTable();
                Da.UpdateCommand = Cb.GetUpdateCommand(); //NO lo añado pq. sino da error de que no soporta
                Da.InsertCommand = Cb.GetInsertCommand();
                Da.DeleteCommand = Cb.GetDeleteCommand();
                Da.Fill(Dt);
                //
                return Dt;
                //
            }
            catch (Exception ex)
            {
                Dt = null; Da = null; Cb = null; return Dt;
                throw ex;
            }
        }
        //'
        /// <summary>
        /// Updatar un dt recuperado con 'RecuperarDt'
        /// </summary>
        /// <param name="dt"></param>
        /// <remarks></remarks>
        public static Exception EjecutarUpdate(DataTable dt, string selectCommand, clsVariables.e_TipoOrigen origen)
        {
            Exception ret = null; // New DataTable
            try
            {
                ConnectionStringSettings c = clsVariables.e_Cc(origen);
                //Dim factory As DbProviderFactory = DbProviderFactories.GetFactory(c.ProviderName)
                using (MySqlConnection Cn = new MySqlConnection(c.ConnectionString))
                {
                    using (MySqlDataAdapter da = new MySqlDataAdapter(selectCommand, c.ConnectionString))
                    {
                        using (MySqlCommandBuilder builder = new MySqlCommandBuilder(da))
                        {
                            //.FillSchema(dsDatos, SchemaType.Source, "NacionalidadPlato")
                            //da.AcceptChangesDuringUpdate = true; //Con esto obtengo el id en tiempo real
                            //da.AcceptChangesDuringFill = true;
                            // da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
                            da.InsertCommand = builder.GetInsertCommand();
                            //Console.WriteLine(builder.GetInsertCommand().CommandText);
                            da.UpdateCommand = builder.GetUpdateCommand();
                            //Console.WriteLine(builder.GetUpdateCommand().CommandText);
                            da.DeleteCommand = builder.GetDeleteCommand();
                            //Console.WriteLine(builder.GetDeleteCommand().CommandText);
                            da.Update(dt);
                        }
                    }
                }

                //
            }
            catch (Exception ex)
            {
                ret = ex;
            }
            return ret;
        }
        //
        /// <summary>
        /// Ejecuta sentencia SQL y devuelve 0 en caso de error, o el numero de registros procesados en caso de exito
        /// </summary>
        /// <param name="strSql"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static int EjecutarSql(string strSql)
        {
            try
            {
                if (strSql.Equals(string.Empty))
                {
                    return 0;
                }
                else
                {
                    //
                    using (MySqlConnection scnMySQLServer = new MySqlConnection(clsVariables.e_CcToString(clsVariables.e_TipoOrigen.Cliente)))
                    {
                        //
                        scnMySQLServer.Open();
                        using (MySqlCommand msqcComando = new MySqlCommand { CommandText = strSql, CommandType = CommandType.Text, Connection = scnMySQLServer })
                        {
                            return msqcComando.ExecuteNonQuery();
                        }
                    }

                }
                //
            }
            catch (Exception ex)
            {
                Utiles.Errores.LanzarError(null, "EjecutarSql", "", ex, MessageBoxIcon.Exclamation, true);
                //Console.WriteLine(String.Format("ExecuteSQLCommand:{0}ex:{1}{0}prmCommando{2}{0}Connection:{3}", vbCrLf, ex.ToString, prmComando, e_CcToString(e_TipoOrigen.Cliente)))
                return 0;
            }
        }
        //
        /// <summary>
        /// Devuelve el núm de registros
        /// </summary>
        /// <param name="strSql"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static int EjecutarExecuteScalar(string strSql)
        {
            try
            {
                if (strSql.Equals(string.Empty))
                {
                    return 0;
                }
                else
                {
                    //Dim scnSQLServer As New SqlConnection
                    MySqlConnection scnMySQLServer = new MySqlConnection(clsVariables.e_CcToString(clsVariables.e_TipoOrigen.Cliente));
                    //Dim sqcComando As New SqlCommand
                    using (MySqlCommand msqcComando = new MySqlCommand())
                    {
                        //
                        scnMySQLServer.Open();
                        msqcComando.CommandText = strSql;
                        msqcComando.CommandType = CommandType.Text;
                        msqcComando.Connection = scnMySQLServer;
                        return (int)msqcComando.ExecuteScalar();
                    } //devuelve el núm de registros
                }
            }
            catch (Exception)
            {
                return 0;
            }
        }

        public static string CrearCopiaSeguridad2(bool _bolCopiaAutomatica, bool _bolMostrarMjeFin = true)
        {
            //NP
            //string comando = null;
            //try
            //{
            //    string comando = Application.StartupPath + "\\mysqldump --host=" + clsVariables.str_NombreBBDDCliente + " --user=" + usuario + " --password=" + contraseña + " --databases " + basedatos + " -r " + ruta;
            //    Shell(comando, AppWinStyle.MinimizedFocus, true);
            //}
            //catch (Exception ex)
            //{
            //    Interaction.MsgBox("Ha ocurrido un error al intentar respaldar la base de datos.", MsgBoxStyle.Critical, "Error al Respaldar");
            //    return;
            //}
            //Interaction.MsgBox("Base de datos respaldada exitosamente", MsgBoxStyle.Information, "Respaldo Exitoso");
            return "";
        }

        /// <summary>
        /// Crear la copia y actualizar la tabla backups
        /// </summary>
        /// <param name="_bolCopiaAutomatica">True o False en campo automatico de tabla backups</param>
        /// <param name="_bolMostrarMjeFin"></param>
        /// <returns></returns>
        public static string CrearCopiaSeguridad(bool _bolCopiaAutomatica, bool _bolMostrarMjeFin = true)
        {
            string _strRutaFolderBackup = string.Empty;
            //''mysqldump --opt --password=miclave --user=miuser mibasededatos > archivo.sql
            //Ejemplo: "C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqldump" -uroot -proot -C -q --opt Maca > 
            //"D:\Temp\MacaBckp.SQL" -- funciona. C = compress y q = quick
            //Buscar mysqldump.exe  
            string[] fileEntries=null;
            string StrDirectorio=string.Empty;
            StrDirectorio = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + "\\MySQL"; //Buscar en X32
            if (System.IO.Directory.Exists(StrDirectorio))
            {
                fileEntries = System.IO.Directory.GetFiles(StrDirectorio, "mysqldump.exe", System.IO.SearchOption.AllDirectories);
            }
            if (fileEntries == null || fileEntries.Length == 0)
            {
                StrDirectorio = Environment.GetEnvironmentVariable("ProgramW6432") + "\\MySQL"; //Buscar en X64
                if (System.IO.Directory.Exists(StrDirectorio))
                {
                    fileEntries = System.IO.Directory.GetFiles(StrDirectorio, "mysqldump.exe",
                                  System.IO.SearchOption.AllDirectories);
                }
            }
            if (fileEntries == null || fileEntries.Length == 0)
            { throw new Exception("No se encuentra el archivo necesario para crear copias de seguridad." + Environment.NewLine +
                "Directorio x86: " + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + Environment.NewLine +
                "Directorio x64: " + Environment.GetEnvironmentVariable("ProgramW6432") + Environment.NewLine);
            }
            else
            {
                string _strFechaAhora = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                string Filename = fileEntries[0]; // @"C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqldump.exe"; 
                string _strPathBackup = String.Format("{0}GescanBackup_{1:yyyyMMdd}", clsVariables.str_PathBackupsBBDD, DateTime.Now);
                if (!System.IO.Directory.Exists(_strPathBackup)) { System.IO.Directory.CreateDirectory(_strPathBackup); } //Crear=
                //Cliente
                string _strCopiaFile = String.Format(@"{0}\Maca_{1}.SQL", _strPathBackup, _strFechaAhora);
                CrearCopia(_strCopiaFile, Filename, clsVariables.e_TipoOrigen.Cliente);
                //Sistema
                _strCopiaFile = String.Format(@"{0}\MacaSistema_{1}.SQL", _strPathBackup, _strFechaAhora);
                CrearCopia(_strCopiaFile, Filename, clsVariables.e_TipoOrigen.Sistema);
                _strRutaFolderBackup = System.IO.Path.GetDirectoryName(_strCopiaFile);
                //insert tabla backups
                string _strSQl = " INSERT INTO backups " +
                                " (fecha, user, rutaficheros, automatico) " +
                                " VALUES ('{0}', {1}, '{2}', {3}); ";
                _strSQl = string.Format(_strSQl, clsBBDD_MySQL.cFecha(DateTime.Now, true),
                            clsVariables.UsuarioActualInfo.intIdUsuario, _strRutaFolderBackup, _bolCopiaAutomatica);
                int _intUpdate = clsBBDD.EjecutarExecuteNonQuery(_strSQl, clsVariables.e_TipoOrigen.Sistema); //Actualizar a true
                if (_intUpdate == -1) { throw new Exception("La copia se ha hecho pero no se ha podido actualizar datos de tabla backups"); }
                //Mje final
                if (_bolMostrarMjeFin && MessageBox.Show(String.Format("La copia se ha realizado con éxito.{1}{1}Ficheros generados en: '{0}'. " +
                                    "{1}{1}Desea abrir la carpeta contenido?", _strPathBackup, Environment.NewLine), clsVariables.str_NombreAplicacion,
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                { Utiles.FicherosCarpetas.AbrirCarpetaConExplorer(_strPathBackup); }
            }
            return _strRutaFolderBackup;
        }
        //
        private static void CrearCopia(string _strCopiaFile, string cmdSQlDump, clsVariables.e_TipoOrigen TipoOrigen)
        {
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(_strCopiaFile, false, System.Text.Encoding.UTF8))
            {
                ProcessStartInfo proc = new ProcessStartInfo();
                string cmd = string.Format(@"-u{0} -p{1} --default-character-set=latin1 -h{2} {3}", 
                    "root", "root", "localhost",
                    TipoOrigen == clsVariables.e_TipoOrigen.Cliente ? clsVariables.str_NombreBBDDCliente : clsVariables.str_NombreBBDDCliente + "Sistema");
                proc.FileName = cmdSQlDump;
                proc.RedirectStandardInput = false;
                proc.RedirectStandardOutput = true;
                proc.Arguments = cmd;
                proc.UseShellExecute = false;
                //proc.WindowStyle = ProcessWindowStyle.Minimized;
                //proc.UseShellExecute = false;
                //proc.WindowStyle = ProcessWindowStyle.Hidden;
                proc.CreateNoWindow = true;
                Process p = Process.Start(proc);
                string res = p.StandardOutput.ReadToEnd();
                file.WriteLine(res);
                p.WaitForExit();
                file.Close();
            }
        }
    }
    //'
}

